﻿using jvm.instructions.common;
using jvm.rtda;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace jvm.instructions.loads
{
    class XALoadUtil
    {
        public static void CheckNotNull(JObject obj)
        {
            if (obj == null)
            {
                Console.WriteLine("java.lang.NullPointerException");
                Environment.Exit(0);
            }
        }

        public static void CheckIndex(int index, int arrayLength)
        {
            if (index < 0 || index >= arrayLength)
            {
                Console.WriteLine("java.lang.IndexOutOfBoundsException");
                Environment.Exit(0);
            }
        }
    }

    class AALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            JObject[] refs = obj.Refs();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushRef(refs[index]);
        }
    }

    class BALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            byte[] refs = obj.Bytes();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushInt(refs[index]);
        }
    }

    class CALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            char[] refs = obj.Chars();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushInt(refs[index]);
        }
    }

    class SALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            short[] refs = obj.Shorts();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushInt(refs[index]);
        }
    }

    class IALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            int[] refs = obj.Ints();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushInt(refs[index]);
        }
    }

    class LALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            long[] refs = obj.Longs();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushLong(refs[index]);
        }
    }

    class FALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            float[] refs = obj.Floats();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushFloat(refs[index]);
        }
    }

    class DALOAD : NoOperandsInstruction
    {
        public override void Execute(JFrame frame)
        {
            int index = frame.operandStack.PopInt();
            JObject obj = frame.operandStack.PopRef();
            XALoadUtil.CheckNotNull(obj);
            double[] refs = obj.Doubles();
            XALoadUtil.CheckIndex(index, refs.Length);
            frame.operandStack.PushDouble(refs[index]);
        }
    }
}
